package com.cardgame.model.level;

import com.cardgame.dao.ArchivalDao;
import com.cardgame.dao.BuffDao;
import com.cardgame.dao.CardDao;
import com.cardgame.dao.RoleDao;
import com.cardgame.model.buff.Buff;
import com.cardgame.model.card.*;
import com.cardgame.model.deck.Deck;
import com.cardgame.model.role.Skill;
import lombok.Getter;

import java.util.*;

@Getter
public class LevelPlayer {
    private final List<Card> cardDeck; // 初始卡组
    private final List<Card> usedCardDeck; // 已使用的卡牌
    private final LevelMainRole mainRole; // 主角色;
    private final List<LevelRole> appearRoles;
    private final List<Card> handCards;

    private final ArchivalDao archivalDao;
    private final CardDao cardDao;
    private final RoleDao roleDao;
    private final BuffDao buffDao;

    public LevelPlayer(ArchivalDao archivalDao, CardDao cardDao, RoleDao roleDao, BuffDao buffDao, int deckId) {
        this.archivalDao = archivalDao;
        this.cardDao = cardDao;
        this.roleDao = roleDao;
        this.buffDao = buffDao;

        Deck deck = archivalDao.getDeckById(deckId);
        if (deck == null)
            throw new IllegalArgumentException("卡组ID无效，无法初始化战斗");

        this.cardDeck = new ArrayList<>();
        for (Map.Entry<Integer, Integer> entry : deck.getCards().entrySet()) {
            Card card = cardDao.getCardById(entry.getKey());
            this.cardDeck.addAll(Collections.nCopies(entry.getValue(), card));
        }
        Collections.shuffle(this.cardDeck);

        this.usedCardDeck = new ArrayList<>();
        this.mainRole = new LevelMainRole(roleDao.getRoleById(deck.getLeaderRoleId()));
        this.appearRoles = new ArrayList<>();
        this.handCards = new ArrayList<>();
    }

    public void DealCards() {
        while (handCards.size() < 5 && !cardDeck.isEmpty()) {
            Card card = cardDeck.removeFirst();
            handCards.add(card);
        }
    }

    public void GetActionCardEffect(ActionCard actionCard) {
        if (actionCard.getAddEnemyHP()!= null)
            mainRole.setCurrentHP(mainRole.getCurrentHP() + actionCard.getAddEnemyHP());
        if (actionCard.getAddEnemyMP()!= null)
            mainRole.setCurrentMP(mainRole.getCurrentMP() + actionCard.getAddEnemyMP());
        if (actionCard.getBuffID() != -1) {
            Buff buff = buffDao.getBuffById(actionCard.getBuffID());
            if (buff!= null) {
                switch (buff.getBuffEffectType()) {
                    case ATTACK_REDUCE:
                    case HP_REDUCE: {
                        appearRoles.forEach(role -> role.addBuff(new LevelBuff(buff)));
                        break;
                    }
                }
            }
        }
    }

    public Optional<ActionCard> UseCard(int cardId, int target) {
        Optional<ActionCard> result = Optional.empty();

        if (handCards.stream().noneMatch(c -> c.getId() == cardId))
            throw new IllegalArgumentException("手牌中不存在该卡牌");
        Card card = handCards.stream().filter(c -> c.getId() == cardId).findFirst().orElseThrow();
        int cardCost = card.getCost();
        if (mainRole.useMP(cardCost))
            throw new IllegalArgumentException("MP不足，无法使用该卡牌");

        switch (card) {
            case RoleCard roleCard -> {
                LevelRole newRole = new LevelRole(roleCard);
                appearRoles.add(newRole);
            }
            case TotalWeaponCard totalWeaponCard -> mainRole.setWeapon(totalWeaponCard);
            case RoleWeaponCard roleWeaponCard -> {
                if (!appearRoles.isEmpty() && target >= 0 && target < appearRoles.size()) {
                    appearRoles.get(target).setWeapon(roleWeaponCard);
                } else {
                    throw new IllegalArgumentException("目标角色不存在");
                }
            }
            default -> {
                ActionCard actionCard = (ActionCard) card;
                if (actionCard.getAddSelfHP() != null)
                    mainRole.setCurrentHP(mainRole.getCurrentHP() + actionCard.getAddSelfHP());
                if (actionCard.getAddSelfMP() != null)
                    mainRole.setCurrentMP(mainRole.getCurrentMP() + actionCard.getAddSelfMP());
                if (actionCard.getAddSelfMPMAX() != null)
                    mainRole.setMaxMP(mainRole.getMaxMP() + actionCard.getAddSelfMPMAX());
                // 新增：为己方场上所有角色添加buff
                if (actionCard.getBuffID() != -1) {
                    Buff buff = buffDao.getBuffById(actionCard.getBuffID());
                    if (buff != null){
                        switch (buff.getBuffEffectType()){
                            case ATTACK_BOOST:
                            case HP_BOOST: {
                                appearRoles.forEach(role -> role.addBuff(new LevelBuff(buff)));
                                break;
                            }
                            case HP_REDUCE:
                            case ATTACK_REDUCE: {
                                result = Optional.of(actionCard);
                                break;
                            }
                        }
                    }
                }
                if (actionCard.getAddEnemyHP()!= null || actionCard.getAddEnemyMP()!= null) {
                    result = Optional.of(actionCard);
                }
            }
        }

        handCards.remove(card);
        usedCardDeck.add(card);
        return result;
    }

    public void GetSkillEffect(Skill skill) {
        if (skill.getAddEnemyHp()!= 0)
            mainRole.setCurrentHP(mainRole.getCurrentHP() + skill.getAddEnemyHp());
        if (skill.getAddEnemyMp()!= 0)
            mainRole.setCurrentMP(mainRole.getCurrentMP() + skill.getAddEnemyMp());
    }

    public Optional<Skill> UseSkill() {
        Optional<Skill> result = Optional.empty();
        if (mainRole.getRole().getSkill() == null)
            throw new IllegalArgumentException("角色没有技能");
        if (mainRole.useMP(mainRole.getRole().getSkill().getCost()))
            throw new IllegalArgumentException("MP不足，无法使用技能");
        Skill skill = mainRole.getRole().getSkill();
        if (skill.getAddSelfHp() != 0)
            mainRole.setCurrentHP(mainRole.getCurrentHP() + skill.getAddSelfHp());
        if (skill.getAddSelfMp() != 0)
            mainRole.setCurrentMP(mainRole.getCurrentMP() + skill.getAddSelfMp());
        if (skill.getAddSelfMpMax() != 0)
            mainRole.setMaxMP(mainRole.getMaxMP() + skill.getAddSelfMpMax());
        if (skill.getAddEnemyHp()!= 0 || skill.getAddEnemyMp()!= 0)
            result = Optional.of(skill);
        return result;
    }

    public boolean EnemyEndTurn(List<Integer> damageList) {
        appearRoles.removeIf(LevelRole::buffEffect);
        Random rand = new Random();
        for (Integer damage : damageList) {
            if (appearRoles.isEmpty()){
                mainRole.setCurrentHP(mainRole.getCurrentHP() - damage);
            } else {
                int target = rand.nextInt(appearRoles.size());
                if (appearRoles.get(target).getAttacked(damage))
                    appearRoles.remove(target);
            }
        }
        return mainRole.getCurrentHP() <= 0;
    }

    public List<Integer> SelfEndTurn() {
        mainRole.resetMP();
        appearRoles.removeIf(LevelRole::buffEffect);
        return appearRoles.stream().map(LevelRole::getAttack).toList();
    }

    @Getter
    public static class AIActionResult {
        List<Optional<ActionCard>> usedCards = new ArrayList<>();
        List<Optional<Skill>> usedSkills = new ArrayList<>();
    }

    /**
     * AI出牌逻辑：根据卡牌加权价值排序，优先打出高价值卡直到耗尽法力。
     */
    public AIActionResult AIAction(){
        AIActionResult result = new AIActionResult();
        // 计算卡牌价值
        Map<Integer, Double> cardValues = new HashMap<>();
        for (Card card : handCards) {
            if (card.getCost() > mainRole.getCurrentMP())
                continue;
            double value = getCardValue(card);
            cardValues.put(card.getId(), value);
        }
        // 按价值排序
        List<Map.Entry<Integer, Double>> sortedCards = new ArrayList<>(cardValues.entrySet());
        sortedCards.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));
        // 选择价值最高的卡牌
        for (Map.Entry<Integer, Double> entry : sortedCards) {
            int cardId = entry.getKey();
            try {
                result.usedCards.add(UseCard(cardId, 0));
            } catch (IllegalArgumentException ignored) {}
        }
        // 检查是否有技能可以使用
        try {
            result.usedSkills.add(UseSkill());
        } catch (IllegalArgumentException ignored) {}
        return result;
    }

    private double getCardValue(Card card) {
        double value;
        switch (card){
            case RoleCard roleCard -> value = roleCard.getHealth() + roleCard.getAttack() * 1.5;
            case RoleWeaponCard roleWeaponCard -> {
                int lastWeaponCount = appearRoles.stream().filter(role -> role.getWeapon() == null).toList().size();
                value = (roleWeaponCard.getAddHPMax() + roleWeaponCard.getAddAttack() * 1.2) * lastWeaponCount;
            }
            case TotalWeaponCard totalWeaponCard -> value = (mainRole.getWeapon() == null ? totalWeaponCard.getAddHPMax() * 0.1 : 0);
            case ActionCard actionCard -> value = (actionCard.getAddSelfMPMAX() != null ? actionCard.getAddSelfMPMAX() * 10.0 : 0)
                        + (actionCard.getAddSelfHP() != null ? actionCard.getAddSelfHP() * 0.1 : 0)
                        + (actionCard.getAddSelfMP() != null ? (actionCard.getAddSelfMP() * 100.0) * (mainRole.getMaxMP() - mainRole.getCurrentMP()) : 0)
                        + (actionCard.getAddEnemyHP() != null ? -actionCard.getAddEnemyHP() * 0.8 : 0)
                        + (actionCard.getBuffID() != -1 ? 5.0 : 0);
            default -> throw new IllegalStateException("Unexpected value: " + card);
        }
        return value;
    }
}
